和为S两个数字
题目来源:剑指offer
题目链接
题目描述
输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
输出描述:
1 | 对应每个测试案例,输出两个数,小的先输出。 |
解法1: 使用set
1 | class Solution { |
时间复杂度分析
时间复杂度为O(n)
空间复杂度为O(n)
解法2:双指针
思路:数组是有序的,可以用双指针。
AC代码:
1 | class Solution { |
时间复杂度分析
时间复杂度为O(n)
空间复杂度为O(1)
和为S的连续正数序列
题目描述
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
输出描述
1 | 输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序 |
解法1
1 | class Solution { |
使用累计和的概念.
ans[i]统计0-i的和.
解法2
AC代码1
1 | class Solution { |
AC代码2
1 | class Solution { |
thisSum表示子数组arr[l,…,r]的累加和. 最初, l=1, r =2, 最小的两个连续正数序列的和为1+2=3.所以,将thisSum初始化为3.
循环结束条件为两个数的和大于等于sum时,因此可知,满足这个条件的最大的子数组为[n, n+1], n = (1+sum)/2.因此,需要循环结束条件为l = (1+sum)/2
Two Sum
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Example:
1 | Given nums = [2, 7, 11, 15], target = 9, |
此题和上题的区别有两点:
- 返回下标,而不是值
- 数组不是有序的
若是返回的是值,可以对数组进行排序然后按双指针解。时间复杂度为O(nlogn)。排序的时间复杂度为O(n)。
解法1:暴力破解
1 | class Solution { |
时间复杂度为O(n2),空间复杂度为O(1)。
解法2:两趟哈希表
1 | class Solution { |
时间复杂度为O(n),空间复杂度为O(n)。
解法3:一趟哈希表
1 | class Solution { |
时间复杂度为O(n),空间复杂度为O(n)。
3Sum
Medium
Given an array nums
of n integers, are there elements a, b, c in nums
such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
The solution set must not contain duplicate triplets.
Example:
1 | Given array nums = [-1, 0, 1, 2, -1, -4], |
思路:首先对数组进行排序。然后锁定第一个数,如第一个数的索引是i,则此后在front-back范围内(front > i)寻找两个数,使他们的和为0 - nums[i]。随着i后移,front和back指定的范围在缩小。因为nums[i]增大,则0 - nums[i]减小。且移动过程中需要去重。
如将上例数据改为:
1 | Given array nums = [-1, 0, 1, 0, 1, 2, -1, -4, 2, 3] |
则排序后:
1 | array nums = [-4, -1, -1, 0, 0, 1, 1, 2, 2, 3] |
过程如下:注意去重
i = 0, front = 1, back = 9, 在front-back中找两个数的和为4
front = 5, back= 9, nums[5]=1, nums[9]=3(front = 6, nums[front]=1,需要去重)
front = 7, back=8, nums[7]=2, nums[8]=2
i = 1, front = 1, back = 9, 在front-back中找两个数的和为1
front = 2, back = 8, nums[2] = -1, nums[8] = 2
front = 3, back = 6, nums[3] = 0, nums[6] = 1(后面back=5, nums[5]=0, 需要去重)
i = 2(nums[2] = -1需要去重)
此题的难点主要在于如何消除重复元素的影响。
有点问题的代码:此代码的问题在于,没有考虑到重复元素的问题。例如
nums = [0,0,0,0]
solution set is [[0,0,0], [0, 0, 0]]
对于考虑到了外重循环遇到重复元素的问题,即对于索引0处的元素和索引1,2,3处的元素都相同,因此,不再统计由索引1,2,3处元素开始的子集合。但是对于内重循环未考虑到当第一个元素确定时,第二个元素和第三个元素重复的问题。
1 | class Solution { |
AC代码
1 | class Solution { |
相关题目
在未排序正数数组中累加和为给定值的最长子数组长度